﻿#ifndef _CELL_EPOLL_SERVER_H_
#define _CELL_EPOLL_SERVER_H_

#if __linux__

#include "CELLServer.hpp"
#include "CELLEpoll.hpp"
#include "CELLClient.hpp"
#include "CELLLog.hpp"

class CELLEpollServer : public CELLServer
{
public:
	CELLEpollServer()
	{
		_ep.create(10240);
	}

	~CELLEpollServer()
	{
		Close();
	}

	virtual bool DoNetEvents() override
	{
		// 检测需要发送给客户端数据的客户端(这个可以根据情况而改变)
		for (auto iter : _clients)
		{
			if (iter.second->needWrite())
			{
				// 如果客户端有数据可发送，那么就检测可写
				_ep.ctl(EPOLL_CTL_MOD, iter.second, EPOLLOUT | EPOLLIN);
			}
			else
			{
				_ep.ctl(EPOLL_CTL_MOD, iter.second, EPOLLIN);
			}
	}
		time_t time = _time_events.getTime();
		if (time <= 0)
			time = -1;
		int ret = _ep.wait(time);
		do {
			if (ret < 0)
			{
				CELLLog_pError("CELLEpollServer::DoNetEvents");
				break;
			}
			else if (ret == 0)
			{
				_time_events.process_timer();
				return true;
			}

			auto events = _ep.events();
			for (int i = 0; i < ret; ++i)
			{
				CELLClient* pClient = (CELLClient*)events[i].data.ptr;
				if (pClient)
				{
					// 客户端可读
					if (events[i].events & EPOLLIN)
					{
						if (RecvData(pClient) == SOCKET_ERROR)
						{
							rmClient(pClient);
							continue;
						}
					}

					// 客户端可写
					if (events[i].events & EPOLLOUT)
					{
						if (pClient->SendDataReal() == SOCKET_ERROR)
						{
							rmClient(pClient);
						}
					}
				}
			}
			return true;
		} while (0);
		_time_events.process_timer();
		return false;
	}

	// 本类中加入客户端加入事件
	virtual void OnClientJoin(CELLClient* pClient)
	{
		_ep.ctl(EPOLL_CTL_ADD, pClient, EPOLLIN);
	}

	// 
	void rmClient(CELLClient* pClient)
	{
		auto iter = _clients.find(pClient->sockfd());
		if (iter != _clients.end())
		{
			_clients.erase(iter);
		}
		// 触发客户端离开事件(里面会删除客户端，所以放在后面)
		OnClientLeave(pClient);
	}
private:
	CELLEpoll _ep;
};

#endif // #if __linux__

#endif // #ifndef _CELL_EPOLL_SERVER_H_
